#include "common_def.h"
#include "soc_osal.h"
#include "securec.h"
#include "product.h"
#include "bts_le_gap.h"
#include "cmsis_os2.h"
#include "time.h"
#include "stdlib.h"
#include "gpio.h"
#include "hal_gpio.h"
#include "tcxo.h"
#include "app_init.h"
#include "pinctrl.h"

#include "sle_server_adv.h"
#include "sle_connection_manager.h"
#include "sle_device_discovery.h"
#include "sle_ssap_server.h"
#include "sle_errcode.h"
#include "sle_server.h"

#include "sensor.h"
#include "task.h"


/* 广播ID */
#define SLE_ADV_HANDLE_DEFAULT 1
/* sle server app uuid for test */
static char g_sle_uuid_app_uuid[UUID_LEN_2] = {0x12, 0x34};
/* server notify property uuid for test */
static char g_sle_property_value[OCTET_BIT_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
/* sle connect acb handle */
static uint16_t g_sle_conn_hdl = 0;
/* sle server handle */
static uint8_t g_server_id = 0;
/* sle service handle */
static uint16_t g_service_handle = 0;
/* sle ntf property handle */
static uint16_t g_property_handle = 0;
/* sle pair acb handle */
uint16_t g_sle_pair_hdl;

#define UUID_16BIT_LEN 2
#define UUID_128BIT_LEN 16
#define SLE_SERVER_LOG "[sle uart server]"
#define SLE_SERVER_INIT_DELAY_MS 1000
static uint8_t sle_base[] = {0x37, 0xBE, 0xA8, 0x80, 0xFC, 0x70, 0x11, 0xEA,
                             0xB7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

#define SENSOR_TASK_STACK (2048) // 子线程栈大小
static SensorControl g_sensor = {0};
static SensorData g_data = {0};
char request[128] = "";
char response[128] = "";

uint16_t get_connect_id(void)
{
    return g_sle_conn_hdl;
}

void encode2byte_little(uint8_t *_ptr, uint16_t data)
{
    *(uint8_t *)((_ptr) + 1) = (uint8_t)((data) >> 0x8);
    *(uint8_t *)(_ptr) = (uint8_t)(data);
}
// UUID设置
void sle_uuid_set_base(sle_uuid_t *out)
{
    errcode_sle_t ret;
    ret = memcpy_s(out->uuid, SLE_UUID_LEN, sle_base, SLE_UUID_LEN);
    if (ret != EOK)
    {
        osal_printk("%s sle_uuid_set_base memcpy fail\n", SLE_SERVER_LOG);
        out->len = 0;
        return;
    }
    out->len = UUID_LEN_2;
}

// UUID转换
void sle_uuid_setu2(uint16_t u2, sle_uuid_t *out)
{
    sle_uuid_set_base(out);
    out->len = UUID_LEN_2;
    encode2byte_little(&out->uuid[UUID_INDEX], u2);
}

// UUID打印函数
void sle_uuid_print(sle_uuid_t *uuid)
{
    if (uuid == NULL)
    {
        osal_printk("%s uuid_print,uuid is null\r\n", SLE_SERVER_LOG);
        return;
    }
    if (uuid->len == UUID_16BIT_LEN)
    {
        osal_printk("%s uuid: %02x %02x.\n", SLE_SERVER_LOG,
                    uuid->uuid[14], uuid->uuid[15]); /* 14 15: uuid index */
    }
    else if (uuid->len == UUID_128BIT_LEN)
    {
        osal_printk("%s uuid: \n", SLE_SERVER_LOG); /* 14 15: uuid index */
        osal_printk("%s 0x%02x 0x%02x 0x%02x \n", SLE_SERVER_LOG, uuid->uuid[0], uuid->uuid[1],
                    uuid->uuid[2], uuid->uuid[3]);
        osal_printk("%s 0x%02x 0x%02x 0x%02x \n", SLE_SERVER_LOG, uuid->uuid[4], uuid->uuid[5],
                    uuid->uuid[6], uuid->uuid[7]);
        osal_printk("%s 0x%02x 0x%02x 0x%02x \n", SLE_SERVER_LOG, uuid->uuid[8], uuid->uuid[9],
                    uuid->uuid[10], uuid->uuid[11]);
        osal_printk("%s 0x%02x 0x%02x 0x%02x \n", SLE_SERVER_LOG, uuid->uuid[12], uuid->uuid[13],
                    uuid->uuid[14], uuid->uuid[15]);
    }
}

void ssaps_mtu_changed_cbk(uint8_t server_id, uint16_t conn_id, ssap_exchange_info_t *mtu_size,
                           errcode_sle_t status)
{
    osal_printk("%s ssaps ssaps_mtu_changed_cbk callback server_id:%x, conn_id:%x, mtu_size:%x, status:%x\r\n",
                SLE_SERVER_LOG, server_id, conn_id, mtu_size->mtu_size, status);
    if (g_sle_pair_hdl == 0)
    {
        g_sle_pair_hdl = conn_id + 1;
    }
}

void ssaps_start_service_cbk(uint8_t server_id, uint16_t handle, errcode_sle_t status)
{
    osal_printk("%s start service cbk callback server_id:%d, handle:%x, status:%x\r\n", SLE_SERVER_LOG,
                server_id, handle, status);
}

void ssaps_add_service_cbk(uint8_t server_id, sle_uuid_t *uuid, uint16_t handle, errcode_sle_t status)
{
    osal_printk("%s add service cbk callback server_id:%x, handle:%x, status:%x\r\n", SLE_SERVER_LOG,
                server_id, handle, status);
    sle_uuid_print(uuid);
}

void ssaps_add_property_cbk(uint8_t server_id, sle_uuid_t *uuid, uint16_t service_handle,
                            uint16_t handle, errcode_sle_t status)
{
    osal_printk("%s add property cbk callback server_id:%x, service_handle:%x,handle:%x, status:%x\r\n",
                SLE_SERVER_LOG, server_id, service_handle, handle, status);
    sle_uuid_print(uuid);
}

void ssaps_add_descriptor_cbk(uint8_t server_id, sle_uuid_t *uuid, uint16_t service_handle,
                              uint16_t property_handle, errcode_sle_t status)
{
    osal_printk("%s add descriptor cbk callback server_id:%x, service_handle:%x, property_handle:%x, \
        status:%x\r\n",
                SLE_SERVER_LOG, server_id, service_handle, property_handle, status);
    sle_uuid_print(uuid);
}

void ssaps_delete_all_service_cbk(uint8_t server_id, errcode_sle_t status)
{
    osal_printk("%s delete all service callback server_id:%x, status:%x\r\n", SLE_SERVER_LOG,
                server_id, status);
}

void ssaps_read_cbk(uint8_t server_id, uint16_t conn_id, ssaps_req_read_cb_t *read_cb_para,
                    errcode_sle_t status)
{
    osal_printk("%s ssaps read request cbk callback server_id:%x, conn_id:%x, handle:%x, status:%x\r\n",
                SLE_SERVER_LOG, server_id, conn_id, read_cb_para->handle, status);
}

void ssaps_write_cbk(uint8_t server_id, uint16_t conn_id, ssaps_req_write_cb_t *write_cb_para,
                     errcode_sle_t status)
{
    osal_printk("%s ssaps write request callback cbk server_id:%x, conn_id:%x, handle:%x, status:%x\r\n",
                SLE_SERVER_LOG, server_id, conn_id, write_cb_para->handle, status);
    osal_printk(" sle uart recived data : %s\r\n", write_cb_para->value);
    
    size_t copy_size = strlen((const char*)write_cb_para->value); 
    size_t safe_size = copy_size;
    if (safe_size > sizeof(request)) {
        safe_size = sizeof(request);  // 截断到目标数组大小
    }
    memcpy(request, write_cb_para->value, safe_size);
    sensor_change(request);
    g_sensor = sensor_get();

    g_data = data_get();
    data_to_string(response,sizeof(response),&g_data);

    if (sle_send_data((uint8_t *)response, strlen(response)) == 0) {
        osal_printk("sle_send_data success!\n");
    }
}

errcode_sle_t sle_ssaps_register_cbks(void)
{
    ssaps_callbacks_t ssaps_cbk = {0};
    ssaps_cbk.start_service_cb = ssaps_start_service_cbk;
    ssaps_cbk.mtu_changed_cb = ssaps_mtu_changed_cbk;
    ssaps_cbk.read_request_cb = ssaps_read_cbk;
    ssaps_cbk.write_request_cb = ssaps_write_cbk;
    ssaps_cbk.delete_all_service_cb = ssaps_delete_all_service_cbk;
    ssaps_cbk.add_descriptor_cb = ssaps_add_descriptor_cbk;
    return ssaps_register_callbacks(&ssaps_cbk);
}

errcode_sle_t sle_uuid_server_service_add(void)
{
    errcode_sle_t ret;
    sle_uuid_t service_uuid = {0};
    sle_uuid_setu2(SLE_UUID_SERVER_SERVICE, &service_uuid);
    // 添加ssap服务
    ret = ssaps_add_service_sync(g_server_id, &service_uuid, 1, &g_service_handle);
    if (ret != ERRCODE_SLE_SUCCESS)
    {
        osal_printk("%s sle uuid add service fail, ret:%x\r\n", SLE_SERVER_LOG, ret);
        return ERRCODE_SLE_FAIL;
    }
    return ERRCODE_SLE_SUCCESS;
}

errcode_sle_t sle_uuid_server_property_add(void)
{
    errcode_sle_t ret;
    ssaps_property_info_t property = {0};
    ssaps_desc_info_t descriptor = {0};
    uint8_t ntf_value[] = {0x01, 0x0};

    property.permissions = SLE_UUID_TEST_PROPERTIES;
    property.operate_indication = SSAP_OPERATE_INDICATION_BIT_READ | SSAP_OPERATE_INDICATION_BIT_NOTIFY;
    sle_uuid_setu2(SLE_UUID_SERVER_NTF_REPORT, &property.uuid);
    property.value = (uint8_t *)osal_vmalloc(sizeof(g_sle_property_value));
    if (property.value == NULL)
    {
        return ERRCODE_SLE_FAIL;
    }
    if (memcpy_s(property.value, sizeof(g_sle_property_value), g_sle_property_value,
                 sizeof(g_sle_property_value)) != EOK)
    {
        osal_vfree(property.value);
        return ERRCODE_SLE_FAIL;
    }
    // 添加ssap特征
    ret = ssaps_add_property_sync(g_server_id, g_service_handle, &property, &g_property_handle);
    if (ret != ERRCODE_SLE_SUCCESS)
    {
        osal_printk("%s sle uart add property fail, ret:%x\r\n", SLE_SERVER_LOG, ret);
        osal_vfree(property.value);
        return ERRCODE_SLE_FAIL;
    }
    descriptor.permissions = SLE_UUID_TEST_DESCRIPTOR;
    descriptor.type = SSAP_DESCRIPTOR_USER_DESCRIPTION;
    descriptor.operate_indication = SSAP_OPERATE_INDICATION_BIT_READ | SSAP_OPERATE_INDICATION_BIT_WRITE;
    descriptor.value = ntf_value;
    descriptor.value_len = sizeof(ntf_value);
    // 添加ssap描述符
    ret = ssaps_add_descriptor_sync(g_server_id, g_service_handle, g_property_handle, &descriptor);
    if (ret != ERRCODE_SLE_SUCCESS)
    {
        osal_printk("%s sle uart add descriptor fail, ret:%x\r\n", SLE_SERVER_LOG, ret);
        osal_vfree(property.value);
        osal_vfree(descriptor.value);
        return ERRCODE_SLE_FAIL;
    }
    osal_vfree(property.value);
    return ERRCODE_SLE_SUCCESS;
}

// 添加服务端
errcode_sle_t sle_server_add(void)
{
    errcode_sle_t ret;
    sle_uuid_t app_uuid = {0};

    osal_printk("%s sle uart add service in\r\n", SLE_SERVER_LOG);
    app_uuid.len = sizeof(g_sle_uuid_app_uuid);
    if (memcpy_s(app_uuid.uuid, app_uuid.len, g_sle_uuid_app_uuid, sizeof(g_sle_uuid_app_uuid)) != EOK)
    {
        return ERRCODE_SLE_FAIL;
    }
    ssaps_register_server(&app_uuid, &g_server_id);
    // 添加ssap服务、特征与描述符
    if (sle_uuid_server_service_add() != ERRCODE_SLE_SUCCESS)
    {
        ssaps_unregister_server(g_server_id);
        return ERRCODE_SLE_FAIL;
    }
    if (sle_uuid_server_property_add() != ERRCODE_SLE_SUCCESS)
    {
        ssaps_unregister_server(g_server_id);
        return ERRCODE_SLE_FAIL;
    }
    osal_printk("%s sle uart add service, server_id:%x, service_handle:%x, property_handle:%x\r\n",
                SLE_SERVER_LOG, g_server_id, g_service_handle, g_property_handle);
    // 开启ssap服务
    ret = ssaps_start_service(g_server_id, g_service_handle);
    if (ret != ERRCODE_SLE_SUCCESS)
    {
        osal_printk("%s sle uart add service fail, ret:%x\r\n", SLE_SERVER_LOG, ret);
        return ERRCODE_SLE_FAIL;
    }
    osal_printk("%s sle uart add service out\r\n", SLE_SERVER_LOG);
    return ERRCODE_SLE_SUCCESS;
}

/* device通过uuid向host发送数据：report */
errcode_sle_t sle_server_send_report_by_uuid(const uint8_t *data, uint8_t len)
{
    errcode_sle_t ret;
    ssaps_ntf_ind_by_uuid_t param = {0};
    param.type = SSAP_PROPERTY_TYPE_VALUE;
    param.start_handle = g_service_handle;
    param.end_handle = g_property_handle;
    param.value_len = len;
    param.value = (uint8_t *)osal_vmalloc(len);
    if (param.value == NULL)
    {
        osal_printk("%s send report new fail\r\n", SLE_SERVER_LOG);
        return ERRCODE_SLE_FAIL;
    }
    if (memcpy_s(param.value, param.value_len, data, len) != EOK)
    {
        osal_printk("%s send input report memcpy fail\r\n", SLE_SERVER_LOG);
        osal_vfree(param.value);
        return ERRCODE_SLE_FAIL;
    }
    sle_uuid_setu2(SLE_UUID_SERVER_NTF_REPORT, &param.uuid);
    ret = ssaps_notify_indicate_by_uuid(g_server_id, g_sle_conn_hdl, &param);
    if (ret != ERRCODE_SLE_SUCCESS)
    {
        osal_printk("%s sle_server_send_report_by_uuid,ssaps_notify_indicate_by_uuid fail :%x\r\n",
                    SLE_SERVER_LOG, ret);
        osal_vfree(param.value);
        return ret;
    }
    osal_vfree(param.value);
    return ERRCODE_SLE_SUCCESS;
}

/* device通过handle向host发送数据：report */
errcode_sle_t sle_server_send_report_by_handle(const uint8_t *data, uint8_t len)
{
    ssaps_ntf_ind_t param = {0};
    uint8_t write_req_data[128] = {0};
    param.handle = g_property_handle;
    param.type = SSAP_PROPERTY_TYPE_VALUE;
    param.value = write_req_data;
    param.value_len = len + 1;
    if (memcpy_s(param.value, param.value_len, data, len) != EOK)
    {
        return ERRCODE_SLE_FAIL;
    }
    return ssaps_notify_indicate(g_server_id, g_sle_conn_hdl, &param);
}

void sle_server_connect_state_changed_cbk(uint16_t conn_id, const sle_addr_t *addr,
                                          sle_acb_state_t conn_state, sle_pair_state_t pair_state, sle_disc_reason_t disc_reason)
{
    osal_printk("%s connect state changed callback conn_id:0x%02x, conn_state:0x%x, pair_state:0x%x, \
        disc_reason:0x%x\r\n",
                SLE_SERVER_LOG, conn_id, conn_state, pair_state, disc_reason);
    osal_printk("%s connect state changed callback addr:%02x:**:**:**:%02x:%02x\r\n", SLE_SERVER_LOG,
                addr->addr[BT_INDEX_0], addr->addr[BT_INDEX_4]);
    if (conn_state == SLE_ACB_STATE_CONNECTED)
    {
        // sle_client_addr = addr;
        g_sle_conn_hdl = conn_id;
        sle_stop_announce(SLE_ADV_HANDLE_DEFAULT);
    }
    else if (conn_state == SLE_ACB_STATE_DISCONNECTED)
    {
        // sle_client_addr = NULL;
        g_sle_conn_hdl = 0;
        g_sle_pair_hdl = 0;
        sle_start_announce(SLE_ADV_HANDLE_DEFAULT);
    }
}

void sle_server_pair_complete_cbk(uint16_t conn_id, const sle_addr_t *addr, errcode_sle_t status)
{
    osal_printk("%s pair complete conn_id:%02x, status:%x\r\n", SLE_SERVER_LOG,
                conn_id, status);
    osal_printk("%s pair complete addr:%02x:**:**:**:%02x:%02x\r\n", SLE_SERVER_LOG,
                addr->addr[BT_INDEX_0], addr->addr[BT_INDEX_4]);
    g_sle_pair_hdl = conn_id + 1;
    ssap_exchange_info_t parameter = {0};
    parameter.mtu_size = 520;
    parameter.version = 1;
    ssaps_set_info(g_server_id, &parameter);
}

void sle_conn_register_cbks(void)
{
    sle_connection_callbacks_t conn_cbks = {0};
    conn_cbks.connect_state_changed_cb = sle_server_connect_state_changed_cbk;
    conn_cbks.pair_complete_cb = sle_server_pair_complete_cbk;
    sle_connection_register_callbacks(&conn_cbks);
}

/* 初始化uuid server */
errcode_sle_t sle_server_init(void)
{
    enable_sle();
    sle_announce_register();
    sle_conn_register_cbks();
    sle_ssaps_register_cbks();
    sle_server_add();
    sle_server_adv_init();
    osal_printk("[sle uart server] init ok\r\n");
    return ERRCODE_SLE_SUCCESS;
}

int sle_send_data(uint8_t *data, uint8_t length)
{
    int ret;
    ret = sle_server_send_report_by_handle(data, length);
    return ret;
}

static void *sle_server_task(const char *arg)
{
    unused(arg);
    sle_server_init();
    return NULL;
}


static void sle_uart_entry(void)
{
    osal_task *sle_task = NULL;
    osal_kthread_lock();
    sle_task = osal_kthread_create((osal_kthread_handler)sle_server_task, 0, "SLEUartDongleTask",
                                      SLE_UART_TASK_STACK_SIZE);
    if (sle_task != NULL) {
        osal_kthread_set_priority(sle_task, SLE_UART_TASK_PRIO);
    } else {
        osal_printk("Failed to create SLEUartDongleTask\n");
    }
}

/* Run the sle_uart_entry. */
app_run(sle_uart_entry);